package freelists
{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.system.*;
	import flash.text.*;
	import flash.utils.*;
	
	public class FreeListTest2 extends Sprite
	{
		private var __logger:TextField = new TextField();
		
		public function FreeListTest2()
		{
			__logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(__logger);
			
			const NUM_COLORS:int = 10000000;
			log("------Unallocated------");
			test(NUM_COLORS);
			preAllocate(NUM_COLORS);
			log("-----Pre-allocated-----");
			test(NUM_COLORS);
		}
		
		private function preAllocate(numColors:int): void
		{
			var i:int;
			var temp:Vector.<Color4LinkedList> = new Vector.<Color4LinkedList>(numColors);
			for (i = 0; i < numColors; ++i)
			{
				temp[i] = Color4LinkedList.getColor();
			}
			for (i = 0; i < numColors; ++i)
			{
				Color4LinkedList.freeColor(temp[i]);
			}
			temp = null;
		}
		
		private function test(numColors:int): void
		{
			var cll:Color4LinkedList;
			var i:int;
			
			// Test with linked list-based free list
			var beforeTime:int = getTimer();
			for (i = 0; i < numColors; ++i)
			{
				cll = Color4LinkedList.getColor();
			}
			var afterTime:int = getTimer();
			log("Allocation from linked list-based free list: " + (afterTime - beforeTime));
		}
		
		private function log(msg:*): void
		{
			__logger.appendText(msg + "\n");
		}
	}
}
class Color4LinkedListNode
{
	public var c:Color4LinkedList;
	public var next:Color4LinkedListNode;
}
class Color4LinkedList
{
	/** Head of the list of already-freed colors */
	private static var __freeColorsHead:Color4LinkedListNode;
	
	/** Head of the list of already-freed nodes */
	private static var __freeNodesHead:Color4LinkedListNode;
	
	public var a:Number;
	public var r:Number;
	public var g:Number;
	public var b:Number;
	
	public function Color4LinkedList(a:Number = 0.0, r:Number = 0.0, g:Number = 0.0, b:Number = 0.0)
	{
		this.a = a;
		this.r = r;
		this.g = g;
		this.b = b;
	}
	
	public static function getColor(a:Number = 0.0, r:Number = 0.0, g:Number = 0.0, b:Number = 0.0): Color4LinkedList
	{
		// Already have one, take the head
		if (__freeColorsHead)
		{
			var headNode:Color4LinkedListNode = __freeColorsHead;
			__freeColorsHead = __freeColorsHead.next;
			
			var color:Color4LinkedList = headNode.c;
			color.a = a;
			color.r = r;
			color.g = g;
			color.b = b;
			
			headNode.c = null;
			headNode.next = __freeNodesHead;
			__freeNodesHead = headNode;
			
			return color;
		}
		// Have none, make new
		return new Color4LinkedList(a, r, g, b);
	}
	
	public static function freeColor(c:Color4LinkedList): void
	{
		// Get a node to put on the free list
		var node:Color4LinkedListNode;
		if (__freeNodesHead)
		{
			node = __freeNodesHead;
			__freeNodesHead = __freeNodesHead.next;
		}
		else
		{
			node = new Color4LinkedListNode();
		}
		node.c = c;
		
		// Add to the head
		node.next = __freeColorsHead;
		__freeColorsHead = node;
	}
}